﻿using PatientManagement.Database;
using PatientManagement.Translators;
using ObjectModels = PatientManagement.Common.ObjectModels;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace PatientManagement.Managers
{
    public class ServiceManager : IPatientManagement
    {
        private static ServiceManager m_ServiceProvider;

        public static ServiceManager Instance
        {
            get
            {
                if (m_ServiceProvider != null)
                {
                    return m_ServiceProvider;
                }
                else
                {
                    m_ServiceProvider = new ServiceManager();
                    return m_ServiceProvider;
                }
            }
        }

        #region Patient

        public int AddPatient(Common.ObjectModels.Patient patient)
        {
            int? id = -1;
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    int result = context.AddPatient(ref id, patient.Name, patient.Address,
                        patient.Birthday, patient.PhoneNumber, patient.Sex, patient.PatientId);

                    return id.Value != -1 ? id.Value : -1;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                return -1;
            }
        }

        #endregion

        #region Drug

        public int AddDrug(Common.ObjectModels.Drug drug)
        {
            int? id = -1;
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    int result = context.AddDrug(ref id, drug.Name, drug.Effect, drug.Amount,
                        drug.Price, drug.Description, drug.AlertAmount);
                    return id.Value != -1 ? id.Value : -1;
                }
            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        public List<Common.ObjectModels.Drug> SearchDrugByName(string name)
        {
            var result = new List<ObjectModels.Drug>();
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    List<GetDrugByNameResult> drugs = context.GetDrugByName(name).ToList();
                    return drugs.ToObjectModels();
                }
            }
            catch (Exception)
            {
                return result;
            }
        }

        public List<Common.ObjectModels.Drug> SearchDrugByQuantity(decimal quantity)
        {
            var result = new List<ObjectModels.Drug>();
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    List<GetDrugByAlertAmountResult> drugs = context.GetDrugByAlertAmount(quantity).ToList();
                    return drugs.ToObjectModels();
                }
            }
            catch (Exception)
            {
                return result;
            }
        }

        public List<ObjectModels.Drug> GetAllGrugs()
        {
            var result = new List<ObjectModels.Drug>();
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetDrugs().ToList().ToObjectModels();
                }
            }
            catch (Exception)
            {
                throw;
            }
            return result;
        }

        public bool RemoveDrug(int id)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return (context.DeleteDrug(id) == 0) ? true : false;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool UpdateDrug(ObjectModels.Drug drug)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    int result = context.UpdateDrug(drug.Id, drug.Name, drug.Effect, drug.Amount,
                        drug.Price, drug.Description, drug.AlertAmount);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        #endregion


        public int AddPatient(Patient patient)
        {
            int? id = null;
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    context.AddPatient(ref id, patient.Name, patient.Address, patient.Birthday, patient.PhoneNumber, patient.Sex, patient.PatientId);
                }
            }
            catch (Exception ex)
            {
            }
            return id.HasValue ? id.Value : -1;
        }

        public Patient GetPatientById(int patientId)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetPatientById(patientId).FirstOrDefault();
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public List<Patient> GetAllPatients()
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetPatients().ToList();
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public bool UpdatePatient(Patient patient)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.UpdatePatient(patient.Id, patient.Name, patient.Address, patient.Birthday, patient.PhoneNumber, patient.Sex);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool DeletePatient(int patientId)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.DeletePatient(patientId);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public List<Prescription> GetPrescriptionByPatientId(int patientId)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetPrescriptionByPatientId(patientId).ToList();
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }


        public List<PrescriptionDetail> GetPrescriptionDetails(int prescriptionId)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetPrescriptionDetailsByPrescriptionId(prescriptionId).ToList();
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public List<PrescriptionTemplate> GetPrescriptionTemplates()
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetPrescriptionTemplates().ToList();
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public int AddPrescription(Prescription prescription)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    int? id = null;
                    context.AddPrescription(prescription.PatientId, prescription.Created, prescription.Description,
                        prescription.Diagnostic, prescription.Prognostic, ref id);
                    return id.Value;
                }
            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        public bool AddPrescriptionDetail(PrescriptionDetail prescriptionDetail)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    bool? isSuccess = false;
                    context.AddPrescriptionDetail(prescriptionDetail.PrescriptionId, prescriptionDetail.DrugId, prescriptionDetail.Price, prescriptionDetail.Amount, prescriptionDetail.Usage, ref isSuccess);
                    return isSuccess.Value;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public int AddPrescriptionTemplate(PrescriptionTemplate template)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    int? id = null;
                    context.AddPrescriptionTemplate(template.Name, template.Description, ref id);
                    return id.HasValue ? id.Value : 0;
                }
            }
            catch (Exception ex)
            {
                return 0;
            }
        }


        public bool AddTemplateDetails(List<Drug> drugs, int prescriptionId)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    int? id = null;
                    foreach (var drug in drugs)
                    {
                        context.AddPrescriptionTemplateDetail(drug.Id, prescriptionId, drug.Description, drug.Amount, ref id);
                    }
                    return true;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }


        public bool DeleteTemplateDetails(int id)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.DeletePrescriptionTemplateDetail(id);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool DeleteTemplate(int id)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.DeletePrescriptionTemplate(id, 0).FirstOrDefault().Result;
                    return result != 0 ? true : false;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public PrescriptionTemplate GetTemplateById(int id)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetTemplateById(id).FirstOrDefault();
                }
            }
            catch (Exception ex)
            {
                return new PrescriptionTemplate();
            }
        }

        public List<PrescriptionTempDetail> GetPrescriptionTempDetail(int templateId)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    return context.GetTemplateDetailsByTemplateId(templateId).ToList();
                }
            }
            catch (Exception ex)
            {
                return new List<PrescriptionTempDetail>();
            }
        }

        public bool UpdateTemplate(PrescriptionTemplate template)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.UpdatePrescriptionTemplate(template.Name, template.Description, template.Id);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool UpdateTemplateDetails(PrescriptionTempDetail detail)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.UpdateTemplateDetail(detail.Id, detail.DrugId, detail.Amount, detail.Usage);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool DeletePrescriptionDetails(int id)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.DeletePrescriptionDetail(id);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool DeletePrescription(int id)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    int? result = 0;
                    context.DeletePrescription(id, ref result);
                    return result != 0 ? true : false;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool UpdatePrescriptionDetails(PrescriptionDetail detail)
        {
            try
            {
                using (var context = new DatabaseDataContext())
                {
                    var result = context.UpdatePrescriptionDetail(detail.Amount, detail.Price, detail.Usage, detail.DrugId, detail.Id);
                    return result != 0 ? false : true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}
